#include "dyna_table.h"
#include "string.h"

//#define DBG_ENABLE
#define DBG_SECTION_NAME "dyna_table"
#define DBG_LEVEL DBG_LOG
#define DBG_COLOR
#include "rtdbg.h"


#ifdef PENDING_EN		

void func_pending_self( struct func_dyna_table_def *obj )
{
	u8 luc_res,luc_temp;
	
	luc_res  = obj->parent.put_index/32 ;
	luc_temp = obj->parent.put_index%32 ;

	obj->pending[luc_res] |= 1<<luc_temp;	
}

void func_pending_task( struct func_dyna_table_def *obj, void *func  )
{
	u8 luc_res,luc_temp;
	s16 index;
	
	index = func_table_find( obj, (u8 (*)(void))func );
	if ( index >= 0 )
	{
		luc_res  = index/32 ;
		luc_temp = index%32 ;

		obj->pending[luc_res] |= 1<<luc_temp ;	
	}
}

void func_resume_task( struct func_dyna_table_def *obj, void *func )
{
	u8 luc_res,luc_temp;
	s16 index;
	
	index = func_table_find( obj, (u8 (*)(void))func );
	if ( index >= 0 )
	{
		luc_res  = index/32 ;
		luc_temp = index%32 ;

		obj->pending[luc_res] &= ~(1<<luc_temp);	
	}			
}

void func_scheduler( struct func_dyna_table_def *obj )
{
	u8  luc_res,luc_temp;
	
	obj->parent.put_index = 0 ;
	
	while ( obj->parent.put_index < obj->parent.get_index )
	{
		luc_res  = obj->parent.put_index/32 ;
		luc_temp = obj->parent.put_index%32 ;
		
		if ( obj->pending[luc_res] &(1<<luc_temp) )
		{
			obj->parent.put_index++;
			continue;
		}
		luc_res = obj->func[obj->parent.put_index]();
		if ( luc_res == 0 )
		{
			obj->parent.is_full = false ;
			obj->parent.get_index--;
			obj->func[ obj->parent.put_index ] = obj->func[ obj->parent.get_index ];
			/* get pending flag */
			luc_res  = obj->parent.get_index/32 ;
			luc_temp = obj->parent.get_index%32 ;	
			if ( obj->pending[luc_res]&(1<<luc_temp) )
			{
				obj->pending[luc_res]&=~(1<<luc_temp);
				
				luc_res  = obj->parent.put_index/32 ;
				luc_temp = obj->parent.put_index%32 ;	
				obj->pending[luc_res]|= 1<<luc_temp ;				
			}
		}
		else
		{
			obj->parent.put_index++;
		}
	}
}
#endif


void func_table_centralized_run( struct func_dyna_table_def *obj )
{
	u8 luc_res;
	obj->parent.put_index = 0 ;
	while ( obj->parent.put_index < obj->parent.get_index )
	{
		luc_res = obj->func[obj->parent.put_index]();
		if ( luc_res == 0 )
		{
			obj->parent.is_full = false ;
			obj->parent.get_index--;
			obj->func[ obj->parent.put_index ] = obj->func[ obj->parent.get_index ];
		}
		else
		{
			obj->parent.put_index++;
		}
	}
}
void func_table_distributed_run(struct func_dyna_table_def *obj)
{
    if (obj->parent.put_index < obj->parent.get_index)
    {
        u8 luc_res;
        luc_res = obj->func[obj->parent.put_index]();
        if (luc_res == 0)
        {
            obj->parent.is_full = false ;
            obj->parent.get_index--;
            obj->func[ obj->parent.put_index ] = obj->func[ obj->parent.get_index ];
        }
        else if (++obj->parent.put_index >= obj->parent.get_index)
        {
            obj->parent.put_index = 0 ;
        }
    }
	else
	{
		obj->parent.put_index = 0 ;
	}
}

u8 func_table_register(struct func_dyna_table_def *obj, u8 (*ptr)(void))
{
    for ( u16 i = 0; i < obj->parent.get_index; i++)
    {
        if (obj->func[i] == ptr)
        {
            return 0;
        }
    }
    if (obj->parent.get_index < obj->parent.buf_size)
    {
        obj->func[obj->parent.get_index] = ptr ;
        if (++obj->parent.get_index == obj->parent.buf_size)
        {
            obj->parent.is_full = true ;
        }
#ifdef FUNC_DEBUG
        if (obj->parent.max_index < obj->parent.get_index)
        {
            obj->parent.max_index = obj->parent.get_index;
        }
#endif
        return 0 ;
    }
    else
    {
        return 1 ;
    }
}

u8 func_table_register_no_check(struct func_dyna_table_def *obj, u8 (*ptr)(void))
{
    if (obj->parent.get_index < obj->parent.buf_size)
    {
        obj->func[obj->parent.get_index] = ptr ;
        if (++obj->parent.get_index == obj->parent.buf_size)
        {
            obj->parent.is_full = true ;
        }
#ifdef FUNC_DEBUG
        if (obj->parent.max_index < obj->parent.get_index)
        {
            obj->parent.max_index = obj->parent.get_index;
        }
#endif
        return 0 ;
    }
    else
    {
        return 1 ;
    }
}

void func_table_delete(struct func_dyna_table_def *obj, u8 (*ptr)(void))
{
    for ( u16 i = 0; i < obj->parent.get_index; i++)
    {
        if (obj->func[i] == ptr)
        {
            obj->parent.get_index--;
            obj->func[i] = obj->func[obj->parent.get_index];
            break;
        }
    }
}
s16 func_table_find( struct func_dyna_table_def *obj, u8 (*ptr)(void) )
{
	s16 ls_res = -1 ;
    for ( u16 i = 0; i < obj->parent.get_index; i++)
    {
        if (obj->func[i] == ptr)
        {
			ls_res = i;
            break;
        }
    }	
	return ls_res;
}

u8 timer_table_register(struct timer_dyna_table_def *obj, struct timer_unit_def *timer )
{
	for ( u16 i=0; i<obj->parent.get_index; i++ )
	{
		if ( obj->timer[i] == timer )
		{
			return 0 ;
		}
	}
	if ( obj->parent.get_index < obj->parent.buf_size )
	{
		obj->timer[ obj->parent.get_index ] = timer;	
        if (++obj->parent.get_index >= obj->parent.buf_size)
        {
            obj->parent.is_full = true ;
        }
#ifdef FUNC_DEBUG
        if (obj->parent.max_index < obj->parent.get_index)
        {
            obj->parent.max_index = obj->parent.get_index;
        }
#endif		
		return 0 ;
	}
	else
	{
		return 1;		
	}
}

u8 timer_table_run(struct timer_dyna_table_def *obj )
{
	obj->parent.put_index = 0 ;
	while ( obj->parent.put_index < obj->parent.get_index )
	{
		if ( obj->timer[ obj->parent.put_index ]->cnt > 0 )
		{
			(obj->timer[ obj->parent.put_index ]->cnt)--;
			obj->parent.put_index++;
		}
		else
		{
			obj->parent.get_index--;
			obj->parent.is_full = false;
		
			void(*ptr_call_back)(void);
		
			ptr_call_back = obj->timer[ obj->parent.put_index ]->call_back;
			obj->timer[ obj->parent.put_index ] = obj->timer[ obj->parent.get_index ];
		
#ifdef	TIMER_CALL_BACK
			if ( ptr_call_back != RT_NULL )
			{
				ptr_call_back();
			}
#endif		
		}
	}
	return 0;
}
u8 timer_table_del(struct timer_dyna_table_def *obj, struct timer_unit_def *timer )
{
	for ( u16 i=0; i<obj->parent.get_index; i++ )
	{
		if ( obj->timer[i] == timer )
		{
			obj->parent.get_index--;
			obj->timer[ obj->parent.put_index ] = obj->timer[ obj->parent.get_index ];
			obj->parent.is_full = false;	
			break;
		}
	}	
	return 0 ;
}











